package com.project.list.collection.old;

import java.util.Arrays;

public class MyArrayList<T> implements MyList<T> {

    /**
     * 默认初始容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 最大容量
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * 存放集合所有的数据，transient表示不能被序列化
     */
    transient Object[] elementData;

    protected transient int modCount = 0;

    /**
     * 数组容量默认为空
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 默认数组大小为0
     */
    private int size = 0;

    public MyArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    @Override
    public boolean add(T t) {
        ensureCapacityInternal(size + 1);
        elementData[size++] = t;
        return true;
    }

    /**
     * 返回集合大小
     *
     * @return
     */
    @Override
    public int size() {
        return this.size;
    }

    /**
     * 强转成T 返回对应对象
     *
     * @param index
     * @return
     */
    @SuppressWarnings("unchecked")
    T elementData(int index) {
        return (T) elementData(index);
    }

    @Override
    public T get(int index) {
        return elementData(index);
    }

    @Override
    public T remove(int index) {
        rangCheck(index);
        modCount++;
        T oldValue = elementData(index);
        int numMoved = size - index - 1;
        if (numMoved > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, numMoved);
        }
        elementData[--size] = null;
        return oldValue;
    }

    /**
     * 判断下表是否越界
     *
     * @param index
     */
    private void rangCheck(int index) {
        if (index >= size) {
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    }

    private String outOfBoundsMsg(int index) {
        return "Index:" + index + ",Size: " + size;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    /**
     * 计算是否扩容 同时判断是否为初始状态
     *
     * @param minCapacity 最小容量 = 数组大小 N + 扩容值1
     */
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    /**
     * 判断数组是否需要扩容
     *
     * @param minCapacity 容量值
     */
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        if (minCapacity - elementData.length > 0) {
            grow(minCapacity);
        }
    }

    /**
     * 判断数组是否为初始状态
     * 如果数组扩容值小于默认值则返回默认值 否则返回该值
     *
     * @param elementData 数组
     * @param minCapacity 最小容量 =数组容量N + 扩容值1
     * @return 10> N ? 10 : N
     */
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //如果数组为空
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    /**
     * 扩容方法
     *
     * @param minCapacity
     */
    private void grow(int minCapacity) {
        //原数组长度
        int oldCapacity = elementData.length;
        //新的长度 = 旧的长度 + 旧的长度的一半
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        if (newCapacity - MAX_ARRAY_SIZE > 0) {
            newCapacity = hugeCapacity(minCapacity);
        }
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    /**
     * 超过集合的最大值则使用integer最大值
     *
     * @param minCapacity
     * @return
     */
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) {
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
    }
}
